package com.smart.community.property.service.impl;

import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.smart.community.commons.entity.property.PropertyCompanyCommunity;
import com.smart.community.commons.result.Result;
import com.smart.community.commons.utils.SecurityUtils;
import com.smart.community.feign.region.dto.RegionDTO;
import com.smart.community.feign.region.service.RegionAddressFeignService;
import com.smart.community.feign.region.service.RegionDataFeignService;
import com.smart.community.property.mapper.PropertyCompanyCommunityMapper;
import com.smart.community.property.service.IPropertyCompanyCommunityService;
import com.smart.community.property.service.DataScopeService;

import io.seata.spring.annotation.GlobalTransactional;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

/**
 * 物业公司社区关联服务实现类
 * @author Wu.Liang
 * @since 2025-01-29
 */
@Slf4j
@Service
@RequiredArgsConstructor
public class PropertyCompanyCommunityServiceImpl extends ServiceImpl<PropertyCompanyCommunityMapper, PropertyCompanyCommunity> implements IPropertyCompanyCommunityService {
	private final RegionDataFeignService regionDataFeignClient;
    private final RegionAddressFeignService regionAddressFeignClient;
    private final DataScopeService dataScopeService;

    @Override
    @GlobalTransactional
    public Result<Void> assignCommunityToPropertyCompany(Long propertyCompanyId, Long communityId,
                                                        LocalDate serviceStartDate, LocalDate serviceEndDate,
                                                        String contractNo, BigDecimal serviceFee, String serviceContent) {
        try {
            // 获取当前用户ID
            Long currentUserId = SecurityUtils.getCurrentUserId();
            log.info("分配社区给物业公司，当前用户ID：{}，物业公司ID：{}，社区ID：{}", currentUserId, propertyCompanyId, communityId);
            
            // 参数验证
            if (propertyCompanyId == null || communityId == null) {
                log.warn("参数验证失败：物业公司ID或社区ID为空");
                return Result.fail(400, "参数不能为空");
            }
            
            // 检查权限
            if (!hasAssignPermission(currentUserId, propertyCompanyId)) {
                log.warn("用户{}无权限为物业公司{}分配社区", currentUserId, propertyCompanyId);
                return Result.fail(403, "无权限进行分配操作");
            }

            // 检查是否已存在关联
            if (isPropertyCompanyAssignedToCommunity(propertyCompanyId, communityId)) {
                log.warn("物业公司{}已关联社区{}，不能重复关联", propertyCompanyId, communityId);
                return Result.fail(400, "该社区已关联此物业公司");
            }

            // 创建关联记录
            PropertyCompanyCommunity relation = new PropertyCompanyCommunity();
            relation.setPropertyCompanyId(propertyCompanyId);
            relation.setCommunityId(communityId);
            relation.setContractNo(contractNo);
            relation.setServiceFee(serviceFee);
            relation.setServiceContent(serviceContent);
            relation.setServiceStartDate(serviceStartDate);
            relation.setServiceEndDate(serviceEndDate);
            relation.setCreateBy(currentUserId);
            relation.setCreateTime(LocalDateTime.now());
            relation.setUpdateBy(currentUserId);
            relation.setUpdateTime(LocalDateTime.now());

            boolean saved = save(relation);
            if (saved) {
                log.info("成功创建物业公司社区关联，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId);
                return Result.success();
            } else {
                log.error("创建物业公司社区关联失败，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId);
                return Result.fail(500, "保存关联记录失败");
            }
        } catch (Exception e) {
            log.error("分配社区给物业公司异常，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId, e);
            return Result.fail(500, "系统异常，分配失败");
        }
    }

    @Override
    @GlobalTransactional
    public Result<String> assignCommunitiesToPropertyCompany(Long propertyCompanyId, List<Long> communityIds) {
        try {
            // 获取当前用户ID
            Long currentUserId = SecurityUtils.getCurrentUserId();
            log.info("分配社区给物业公司，当前用户ID：{}，物业公司ID：{}，社区ID列表：{}", currentUserId, propertyCompanyId, communityIds);
            
            // 参数验证
            if (propertyCompanyId == null || communityIds == null || communityIds.isEmpty()) {
                log.warn("参数验证失败：物业公司ID或社区ID列表为空");
                return Result.fail(400, "参数不能为空");
            }
            
            // 检查权限
            if (!hasAssignPermission(currentUserId, propertyCompanyId)) {
                log.warn("用户{}无权限为物业公司{}分配社区", currentUserId, propertyCompanyId);
                return Result.fail(403, "无权限进行分配操作");
            }

            // 批量插入关联关系
            int successCount = 0;
            for (Long communityId : communityIds) {
                if (communityId != null && !isPropertyCompanyAssignedToCommunity(propertyCompanyId, communityId)) {
                    PropertyCompanyCommunity relation = new PropertyCompanyCommunity();
                    relation.setPropertyCompanyId(propertyCompanyId);
                    relation.setCommunityId(communityId);
                    relation.setCreateBy(currentUserId);
                    relation.setCreateTime(LocalDateTime.now());
                    relation.setUpdateBy(currentUserId);
                    relation.setUpdateTime(LocalDateTime.now());
                    
                    boolean saved = save(relation);
                    if (saved) {
                        successCount++;
                        log.info("成功创建物业公司社区关联，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId);
                    } else {
                        log.error("创建物业公司社区关联失败，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId);
                    }
                } else {
                    log.info("物业公司{}已关联社区{}，跳过重复关联", propertyCompanyId, communityId);
                }
            }
            
            log.info("分配社区给物业公司完成，物业公司ID：{}，成功关联数量：{}", propertyCompanyId, successCount);
            return Result.success("分配成功，成功关联" + successCount + "个社区");
        } catch (Exception e) {
            log.error("批量分配社区给物业公司异常，物业公司ID：{}，社区ID列表：{}", propertyCompanyId, communityIds, e);
            return Result.fail(500, "系统异常，分配失败");
        }
    }
    
    @Override
    @GlobalTransactional
    public void assignCommunitiesToPropertyCompanyWithoutPermission(Long propertyCompanyId, List<Long> communityIds) {
        log.info("Feign接口：分配社区给物业公司（跳过权限检查），物业公司ID：{}，社区ID列表：{}", propertyCompanyId, communityIds);
        
        // 批量插入关联关系
        int successCount = 0;
        for (Long communityId : communityIds) {
            // 检查是否已存在关联
            if (!isPropertyCompanyAssignedToCommunity(propertyCompanyId, communityId)) {
                // 创建关联记录
                PropertyCompanyCommunity relation = new PropertyCompanyCommunity();
                relation.setPropertyCompanyId(propertyCompanyId);
                relation.setCommunityId(communityId);
                relation.setCreateTime(LocalDateTime.now());
                relation.setUpdateTime(LocalDateTime.now());
                
                // 保存关联关系
                boolean saved = save(relation);
                if (saved) {
                    successCount++;
                    log.info("Feign接口：成功为物业公司{}分配社区{}", propertyCompanyId, communityId);
                } else {
                    log.error("Feign接口：创建物业公司社区关联失败，物业公司ID：{}，社区ID：{}", propertyCompanyId, communityId);
                }
            } else {
                log.warn("Feign接口：物业公司{}已关联社区{}，跳过重复分配", propertyCompanyId, communityId);
            }
        }
        
        log.info("Feign接口：分配社区给物业公司成功，物业公司ID：{}，成功分配数量：{}", propertyCompanyId, successCount);
    }

    @Override
    @GlobalTransactional
    public Result<String> removePropertyCompanyCommunity(Long id) {
        try {
            // 获取当前用户ID
            Long currentUserId = SecurityUtils.getCurrentUserId();
            log.info("移除物业公司社区关联，当前用户ID：{}，关联ID：{}", currentUserId, id);
            
            // 参数验证
            if (id == null) {
                log.warn("参数验证失败：关联ID为空");
                return Result.fail(400, "关联ID不能为空");
            }
            
            // 检查权限
            if (!hasRemovePermission(currentUserId, id)) {
                log.warn("用户{}无权限移除关联ID{}", currentUserId, id);
                return Result.fail(403, "无权限进行移除操作");
            }

            boolean removed = removeById(id);
            if (removed) {
                log.info("成功移除物业公司社区关联，关联ID：{}", id);
                return Result.success("移除成功");
            } else {
                log.warn("关联记录不存在，关联ID：{}", id);
                return Result.fail(404, "关联记录不存在");
            }
        } catch (Exception e) {
            log.error("移除物业公司社区关联异常，关联ID：{}", id, e);
            return Result.fail(500, "系统异常，移除失败");
        }
    }

    @Override
    @GlobalTransactional
    public Result<String> batchRemovePropertyCompanyCommunities(Long propertyCompanyId, List<Long> communityIds) {
        try {
            // 获取当前用户ID
            Long currentUserId = SecurityUtils.getCurrentUserId();
            log.info("批量移除物业公司社区关联，当前用户ID：{}，物业公司ID：{}，社区ID列表：{}", currentUserId, propertyCompanyId, communityIds);
            
            // 参数验证
            if (propertyCompanyId == null || communityIds == null || communityIds.isEmpty()) {
                log.warn("参数验证失败：物业公司ID或社区ID列表为空");
                return Result.fail(400, "参数不能为空");
            }
            
            // 检查权限
            if (!hasAssignPermission(currentUserId, propertyCompanyId)) {
                log.warn("用户{}无权限为物业公司{}批量移除社区关联", currentUserId, propertyCompanyId);
                return Result.fail(403, "无权限进行批量移除操作");
            }

            LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PropertyCompanyCommunity::getPropertyCompanyId, propertyCompanyId)
                   .in(PropertyCompanyCommunity::getCommunityId, communityIds);

            boolean removed = remove(wrapper);
            if (removed) {
                log.info("成功批量移除物业公司社区关联，物业公司ID：{}，移除数量：{}", propertyCompanyId, communityIds.size());
                return Result.success("批量移除成功");
            } else {
                log.warn("未找到相关关联记录，物业公司ID：{}，社区ID列表：{}", propertyCompanyId, communityIds);
                return Result.fail(404, "未找到相关关联记录");
            }
        } catch (Exception e) {
            log.error("批量移除物业公司社区关联异常，物业公司ID：{}，社区ID列表：{}", propertyCompanyId, communityIds, e);
            return Result.fail(500, "系统异常，批量移除失败");
        }
    }

    @Override
    @GlobalTransactional
    public Result<Void> updatePropertyCompanyCommunityInfo(Long propertyCompanyId, Long communityId,
                                                          LocalDate serviceStartDate, LocalDate serviceEndDate,
                                                          String contractNo, BigDecimal serviceFee, String serviceContent) {
            LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
            wrapper.eq(PropertyCompanyCommunity::getPropertyCompanyId, propertyCompanyId)
                   .eq(PropertyCompanyCommunity::getCommunityId, communityId)
                   .last("LIMIT 1");

            PropertyCompanyCommunity relation = getOne(wrapper);
            if (relation == null) {
                return Result.fail(404, "关联记录不存在");
            }

            relation.setContractNo(contractNo);
            relation.setServiceFee(serviceFee);
            relation.setServiceContent(serviceContent);
            relation.setServiceStartDate(serviceStartDate);
            relation.setServiceEndDate(serviceEndDate);
            relation.setUpdateBy(SecurityUtils.getCurrentUserId());
            relation.setUpdateTime(LocalDateTime.now());

            updateById(relation);
            return Result.success();
    }

    @Override
    public List<PropertyCompanyCommunity> getPropertyCompanyCommunities(Long propertyCompanyId) {
        LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PropertyCompanyCommunity::getPropertyCompanyId, propertyCompanyId)
               .orderByDesc(PropertyCompanyCommunity::getCreateTime);
        return list(wrapper);
    }

    @Override
    public List<Long> getCommunityIdsByPropertyCompanyId(Long propertyCompanyId) {
        log.info("根据物业公司ID获取关联的社区ID集合，物业公司ID：{}", propertyCompanyId);
        try {
            List<PropertyCompanyCommunity> relations = getPropertyCompanyCommunities(propertyCompanyId);
            List<Long> communityIds = relations.stream()
                    .map(PropertyCompanyCommunity::getCommunityId)
                    .collect(Collectors.toList());
            
            log.info("物业公司{}关联的社区数量：{}", propertyCompanyId, communityIds.size());
            return communityIds;
        } catch (Exception e) {
            log.warn("根据物业公司ID获取关联的社区ID集合失败，物业公司ID：{}", propertyCompanyId, e);
            return new ArrayList<>();
        }
    }

    @Override
    public List<PropertyCompanyCommunity> getCommunityPropertyCompanies(Long communityId) {
        LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PropertyCompanyCommunity::getCommunityId, communityId)
               .orderByDesc(PropertyCompanyCommunity::getCreateTime);
        return list(wrapper);
    }

    @Override
    public PropertyCompanyCommunity getCurrentPropertyCompanyForCommunity(Long communityId) {
        LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PropertyCompanyCommunity::getCommunityId, communityId)
               .last("LIMIT 1");
        return getOne(wrapper);
    }

    @Override
    public Long getPropertyCompanyIdByCommunityId(Long communityId) {
        log.info("根据社区ID获取物业公司ID，社区ID：{}", communityId);
        try {
            PropertyCompanyCommunity relation = getCurrentPropertyCompanyForCommunity(communityId);
            if (relation != null) {
                Long propertyCompanyId = relation.getPropertyCompanyId();
                log.info("根据社区ID获取物业公司ID成功，社区ID：{}，物业公司ID：{}", communityId, propertyCompanyId);
                return propertyCompanyId;
            } else {
                log.info("社区ID：{} 未关联任何物业公司", communityId);
                return null;
            }
        } catch (Exception e) {
            log.error("根据社区ID获取物业公司ID失败，社区ID：{}", communityId, e);
            return null;
        }
    }

    @Override
    public Object getPropertyCompanyCommunityStats(Long propertyCompanyId) {
        LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PropertyCompanyCommunity::getPropertyCompanyId, propertyCompanyId);
        long count = count(wrapper);
        
        Map<String, Object> stats = new HashMap<>();
        stats.put("propertyCompanyId", propertyCompanyId);
        stats.put("totalCommunities", count);
        return stats;
    }

    @Override
    public List<Object> getAvailableCommunities(Long propertyCompanyId, String searchKeyword) {
        log.info("获取可分配的社区列表，物业公司ID：{}，搜索关键词：{}", propertyCompanyId, searchKeyword);
        try {
            // 调用区域服务获取所有启用的社区列表
            List<com.smart.community.feign.region.dto.CommunityInfoDTO> allCommunities = 
                regionAddressFeignClient.getAllCommunities();
            
            // 获取已分配的社区ID列表
            List<PropertyCompanyCommunity> assignedCommunities = getPropertyCompanyCommunities(propertyCompanyId);
            Set<Long> assignedCommunityIds = assignedCommunities.stream()
                    .map(PropertyCompanyCommunity::getCommunityId)
                    .collect(Collectors.toSet());
            
            // 过滤出未分配的社区，并获取区域路径信息
            List<Map<String, Object>> availableCommunities = new ArrayList<>();
            
            for (com.smart.community.feign.region.dto.CommunityInfoDTO community : allCommunities) {
                if (!assignedCommunityIds.contains(community.getId())) {
                    Map<String, Object> communityInfo = new HashMap<>();
                    communityInfo.put("id", community.getId());
                    communityInfo.put("communityName", community.getCommunityName());
                    communityInfo.put("communityCode", community.getCommunityCode());
                    communityInfo.put("address", community.getAddress() != null ? community.getAddress() : "");
                    
                    // 获取区域完整路径信息
                    try {
                        List<RegionDTO> pathResultData = regionDataFeignClient.getRegionPath(community.getRegionId());
                        if (pathResultData != null && pathResultData.size() > 0) {
                            String regionFullName = pathResultData.stream()
                                    .map(RegionDTO::getRegionName)
                                    .collect(Collectors.joining(" / "));
                            communityInfo.put("regionFullName", regionFullName);
                        } else {
                            communityInfo.put("regionFullName", community.getCommunityName());
                        }
                    } catch (Exception e) {
                        log.warn("获取社区区域路径失败，社区ID：{}", community.getId(), e);
                        communityInfo.put("regionFullName", community.getCommunityName());
                    }
                    
                    availableCommunities.add(communityInfo);
                }
            }
            
            // 如果有搜索关键词，进行过滤
            if (StringUtils.hasText(searchKeyword)) {
                availableCommunities = availableCommunities.stream()
                        .filter(communityInfo -> {
                            String communityName = (String) communityInfo.get("communityName");
                            String regionFullName = (String) communityInfo.get("regionFullName");
                            return (communityName != null && communityName.toLowerCase().contains(searchKeyword.toLowerCase())) ||
                                   (regionFullName != null && regionFullName.toLowerCase().contains(searchKeyword.toLowerCase()));
                        })
                        .collect(Collectors.toList());
            }
            
            log.info("获取可分配的社区列表成功，物业公司ID：{}，可分配社区数量：{}", propertyCompanyId, availableCommunities.size());
            return new ArrayList<>(availableCommunities);
            
        } catch (Exception e) {
            log.warn("获取可分配的社区列表失败，物业公司ID：{}", propertyCompanyId, e);
            return new ArrayList<>();
        }
    }

    @Override
    public boolean isPropertyCompanyAssignedToCommunity(Long propertyCompanyId, Long communityId) {
        LambdaQueryWrapper<PropertyCompanyCommunity> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(PropertyCompanyCommunity::getPropertyCompanyId, propertyCompanyId)
               .eq(PropertyCompanyCommunity::getCommunityId, communityId);
        return count(wrapper) > 0;
    }


    /**
     * 检查用户是否有分配权限
     * 统一使用DataScopeService进行权限检查，避免重复实现
     * 
     * @param userId 用户ID
     * @param propertyCompanyId 物业公司ID
     * @return 是否有权限
     */
    @Override
    public boolean hasAssignPermission(Long userId, Long propertyCompanyId) {
        log.info("检查用户社区分配权限，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId);
        
        try {
            // 统一使用DataScopeService进行权限检查
            boolean hasPermission = dataScopeService.hasPropertyCompanyPermission(userId, propertyCompanyId);
            log.info("用户{}社区分配权限检查结果：{}", userId, hasPermission);
            return hasPermission;
        } catch (Exception e) {
            log.warn("检查用户社区分配权限失败，用户ID：{}，物业公司ID：{}", userId, propertyCompanyId, e);
            return false;
        }
    }

    /**
     * 检查用户是否有移除权限
     * 统一使用DataScopeService进行权限检查，避免重复实现
     * 
     * @param userId 用户ID
     * @param id 关联记录ID
     * @return 是否有权限
     */
    @Override
    public boolean hasRemovePermission(Long userId, Long id) {
        log.info("检查用户移除权限，用户ID：{}，关联记录ID：{}", userId, id);
        
        try {
            // 先获取关联记录，确定物业公司ID
            PropertyCompanyCommunity relation = getById(id);
            if (relation == null) {
                log.warn("关联记录不存在，ID：{}", id);
                return false;
            }
            
            // 统一使用DataScopeService进行权限检查
            boolean hasPermission = dataScopeService.hasPropertyCompanyPermission(userId, relation.getPropertyCompanyId());
            log.info("用户{}移除权限检查结果：{}", userId, hasPermission);
            return hasPermission;
        } catch (Exception e) {
            log.warn("检查用户移除权限失败，用户ID：{}，关联记录ID：{}", userId, id, e);
            return false;
        }
    }
}
